﻿using Corina.Common;
using Corina.Enumerations;
using Corina.Infrastructure;
using Corina.Win.Interface;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NATUPNPLib;
using System.Net;
using System.Net.Sockets;
using System.Windows.Input;
using Corina.Commands;
using System.Collections.ObjectModel;

namespace Corina.Addins.NatUPnP
{
    [Export(typeof(IView))]
    public class NatUPnPViewmodel : BaseClass, IView
    {
        UPnPNAT upnpnat = new UPnPNAT();

        public NatUPnPViewmodel() {
            Title = "NatUPnP穿透";
            UriString = "NatUPnPView";
            UriType = Enumerations.UriType.InApp;
            Icon = "ICON_MEMORY_CARD";
            GetUPnPCollection();
        }

        #region Fields
        private int _pageIndex = 0;
        private string _title;
        private string _uriString;
        private UriType _uriType = UriType.OutApp;
        private string _icon;
        private int _index = 0;
        #endregion

        #region Properties
        public int PageIndex
        {
            get { return _pageIndex; }
            set
            {
                _pageIndex = value;
                RaisePropertyChanged(() => PageIndex);
            }
        }

        public string Icon
        {
            get { return _icon; }
            set
            {
                _icon = value;
                RaisePropertyChanged(() => Icon);
            }
        }

        public string Title
        {
            get { return _title; }
            set
            {
                _title = value;
                RaisePropertyChanged(() => Title);
            }
        }

        public string UriString
        {
            get { return _uriString; }
            set
            {
                _uriString = value;
                RaisePropertyChanged(() => UriString);
                RaisePropertyChanged(() => FullUrl);
            }
        }

        public UriType UriType
        {
            get { return _uriType; }
            set
            {
                _uriType = value;
                RaisePropertyChanged(() => UriType);
                RaisePropertyChanged(() => FullUrl);
            }
        }

        public string FullUrl
        {
            get
            {
                return UrlPrefix<NatUPnPViewmodel>.Prefixs.FirstOrDefault(k => k.Key == UriType).Value + "Views/" + UriString + ".xaml";
            }
        }

        public int Index
        {
            get { return _index; }
            set
            {
                _index = value;
                RaisePropertyChanged(() => Index);
            }
        }
        #endregion

        #region NAT
        public IEnumerable<string> ProtocolCollection
        {
            get
            {
                yield return "TCP";
                yield return "UDP";
            }
        }

        private string _selectedProtocol = "TCP";
        public string SelectedProtocol
        {
            get { return _selectedProtocol; }
            set
            {
                _selectedProtocol = value;
                RaisePropertyChanged(() => SelectedProtocol);
            }
        }

        public string HostName
        {
            get
            {
                return Dns.GetHostName();
            }
        }

        public IPAddress IPAddress
        {
            get
            {
                return Dns.GetHostEntry(HostName).AddressList.Where(i => i.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault();
            }
        }

        private int _eport = 80;
        public int Eport
        {
            get { return _eport; }
            set
            {
                _eport = value;
                RaisePropertyChanged(() => Eport);
            }
        }

        private int _iport = 80;
        public int Iport
        {
            get { return _iport; }
            set
            {
                _iport = value;
                RaisePropertyChanged(() => Iport);
            }
        }

        private string _description = "NAT UPnP穿透";
        public string Description
        {
            get { return _description; }
            set
            {
                _description = value;
                RaisePropertyChanged(() => Description);
            }
        }

        public ICommand PenetrateCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate
                    {
                        return true;
                    },
                    ExecuteCallback = delegate
                    {
                        var mappings = upnpnat.StaticPortMappingCollection;
                        
                        if (mappings == null)
                        {
                            Console.WriteLine("没有检测到路由器，或者路由器不支持UPnP功能。");
                            return;
                        }

                        mappings.Add(Eport, SelectedProtocol, Iport, IPAddress.ToString(), true, Description);
                    }
                };
            }
        }
        #endregion

        #region Collection

        private void GetUPnPCollection()
        {
            var mappings = upnpnat.StaticPortMappingCollection;

            if (mappings == null)
            {
                Console.WriteLine("没有检测到路由器，或者路由器不支持UPnP功能。");
                return;
            }

            else
            {
                //foreach(var item in mappings)
                //{
                //    UPnPCollection.Add(item);
                //}
            }
        }

        private ObservableCollection<object> _upnpCollection = new ObservableCollection<object>();
        public ObservableCollection<object> UPnPCollection
        {
            get { return _upnpCollection; }
            set
            {
                _upnpCollection = value;
                RaisePropertyChanged(() => UPnPCollection);
            }
        }
        #endregion
    }
}
